package com.huijie.core.util;

import org.springframework.util.StringUtils;

import java.text.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;


/**
 * @ClassName: DateUtil
 * @Description: 日期工具
 * @author JsonY
 * @date 2017年9月18日 下午4:50:31
 * 
 */
public class DateUtil
{
	public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
	public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
	public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
	public static final String QFT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm";

	/** yyyyMMddHHmmss */
	public static final String XIUMA_DATETIME_FORMAT = "yyyyMMddHHmmss";
	/** yyyyMMdd */
	public static final String XIUMA_DATE_FORMAT = "yyyyMMdd";

    public static final String DATE_FORMAT_COMMON="yyyy/MM/dd HH:mm:ss";
    public static final String DATE_FORMAT_SAP="yyyyMMdd";
    public static final String DATE_FORMAT_MINUTE="yyyy/MM/dd HH:mm";

    public static final DateTimeFormatter DEFAULT_DATETIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter DEFAULT_DATE= DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final ZoneId ZONE = ZoneId.systemDefault();

	/** date formart : yyyyMMddHHmmss */
	public static String toStringXiumaDateTime(Date d)
	{
		return toString(d, XIUMA_DATETIME_FORMAT);
	}

	/** date formart : yyyyMMdd */
	public static String toStringXiumaDate(Date d)
	{
		return toString(d, XIUMA_DATE_FORMAT);
	}

	/** date formart : yyyyMMddHHmmss */
	public static Date toDateXiumaDateTime(String d)
	{
		return toDate(d, XIUMA_DATETIME_FORMAT);
	}

	/** date formart : yyyyMMdd */
	public static Date toDateXiumaDate(String d)
	{
		return toDate(d, XIUMA_DATE_FORMAT);
	}

	public static int MONTH_LENGTH = 12;


	/**
	 * 日期字符串转换, 页面显示格式转换为XIUMA数据库存储格式 2006-11-14 => 20061114
	 */
	public static String transxiuma(String src)
	{
		if (src == null)
		{
			return null;
		}
		char dateSymbol = '-';
		if (src.indexOf(dateSymbol) < 0)
		{
			return src;
		}
		Date d = toDate(src, DEFAULT_DATE_FORMAT);
		return toStringXiumaDate(d);
	}

	/**
	 * 日期字符串转换, XIUMA数据库存储格式转换为页面显示格式 20061114 => 2006-11-14
	 */
	public static String trans2view(String src)
	{
		if (StringUtils.isEmpty(src))
		{
			return "";
		}
		//		return src.substring(0, 4) + src.substring(4, 6) + src.substring(6);
		Date d = toDateXiumaDate(src);
		return toString(d, DEFAULT_DATE_FORMAT);
	}


	/**
	 * 日期字符串转换, XIUMA数据库存储格式转换为页面显示格式 20061114055545 => 2006-11-14 05:55
	 */
	public static String trans2viewTime(String src)
	{
		if (StringUtils.isEmpty(src))
		{
			return "";
		}

		Date d = toDateXiumaDateTime(src);
		return toString(d, "yyyy-MM-dd HH:mm");
	}

	/**
	 * 日期字符串转换, XIUMA数据库存储格式转换为页面显示格式 20061114055545 => 2006-11-14 05:55:45
	 */
	public static String trans3viewTime(String src)
	{
		if (StringUtils.isEmpty(src))
		{
			return "";
		}

		Date d = toDateXiumaDateTime(src);
		return toString(d, DEFAULT_DATETIME_FORMAT);
	}

	private static final double[] LIMITS =
	{ 0, 1, 2 };

	private static final String[] MINUTES_PART =
	{ "", "1 minute ", "{0,number} minutes " };

	private static final String[] SECONDS_PART =
	{ "0 seconds", "1 second", "{1,number} seconds" };

	private static final ChoiceFormat MINUTES_FORMAT = new ChoiceFormat(LIMITS, MINUTES_PART);

	private static final ChoiceFormat SECONDS_FORMAT = new ChoiceFormat(LIMITS, SECONDS_PART);

	private static final MessageFormat MINUTE_SECONDS = new MessageFormat("{0}{1}");

	static
	{
		MINUTE_SECONDS.setFormat(0, MINUTES_FORMAT);
		MINUTE_SECONDS.setFormat(1, SECONDS_FORMAT);
	}


	public static final long ONE_DAY = 24 * 60 * 60 * 1000L;

	public static String toString(Date date, String format)
	{

		SimpleDateFormat formatter;

		if ((date == null) || (format == null) || (format.length() == 0))
		{
			return null;
		}
		formatter = new SimpleDateFormat(format);
		return formatter.format(date);
	}

	public static String toString(String str, String format) throws ParseException
	{

		SimpleDateFormat formatter;

		if ((str == null) || (format == null) || (format.length() == 0))
		{
			return null;
		}
		formatter = new SimpleDateFormat(format);
		Date date = formatter.parse(str);
		return formatter.format(date);
	}


	public static Date toDate(String str, String format)
	{
		if ((str == null) || (str.length() == 0) || (format == null) || (format.length() == 0))
		{
			return null;
		}

		SimpleDateFormat formatter = new SimpleDateFormat(format);
		formatter.setLenient(false);
		ParsePosition pos = new ParsePosition(0);
		return formatter.parse(str, pos);
	}

	public static boolean compare(Date date1, Date date2)
	{
		if (date1 == null && date2 == null)
		{
			return true;
		}
		if (date1 == null || date2 == null) {
			return false;
		} else {
			return date1.getTime() == date2.getTime();
		}
	}

	/**
	 * 字符串转换成Date
	 * 
	 * @param str
	 * @return
	 */
	public static Date toDate(String str)
	{
		try
		{
		    char colonSymbol = ':';
			if (str.indexOf(colonSymbol) > 0)
			{
				return toDate(str, DEFAULT_DATETIME_FORMAT);
			}
			else
			{
				return toDate(str, DEFAULT_DATE_FORMAT);
			}
		}
		catch (Exception ex)
		{
			return null;
		}
	}



	public static String currentDateToString(String format)
	{
		Date date = new Date();
		return toString(date, format);
	}

	public static String curDateStr()
	{
		return new SimpleDateFormat(DEFAULT_DATE_FORMAT).format(new Date());
	}

	public String curDateTimeStr()
	{
		return new SimpleDateFormat(DEFAULT_DATETIME_FORMAT).format(new Date());
	}

	public static String formatElapsedTime(long millis)
	{
		long seconds = millis / 1000;
		long minutes = seconds / 60;
		Object[] args =
		{ new Long(minutes), new Long(seconds % 60) };
		return MINUTE_SECONDS.format(args);
	}



	/**
	 * 取得指定月份的第一天日期
	 * 
	 * @param year
	 * @param month
	 * @return
	 */
	public static String getFirstDateOfMonth(int year, int month)
	{
		if (year < 0 || month > MONTH_LENGTH || month < 1) {
			return null;
		}
		return year + (month < 10 ? ("0" + month) : ("" + month)) + "01";
	}

	/**
	 * 取得指定月份的最后一天日期
	 * 
	 * @param year
	 * @param month
	 * @return
	 */
	public static String getLastDateOfMonth(int year, int month)
	{
		if (year < 0 || month > MONTH_LENGTH || month < 1) {
			return null;
		}

		Calendar cal = Calendar.getInstance();
        //下个月的第一天
		cal.set(year, month, 1);
        //减一天
		cal.add(Calendar.DATE, -1);

		int day = cal.get(Calendar.DATE);

		return year + (month < 10 ? ("0" + month) : ("" + month)) + (day < 10 ? ("0" + day) : ("" + day));
	}

	/**
	 * 取得指定日期的相隔天数对应的日期
	 * 
	 * @param year
	 * @param month
	 * @param day
	 * @param days
	 *           相隔天数
	 * @return
	 */
	public static int[] findYearMonthAndDay(int year, int month, int day, int days)
	{
		int[] result = new int[3];
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, day);
		cal.add(Calendar.DATE, days);

		result[0] = cal.get(Calendar.YEAR);
		result[1] = cal.get(Calendar.MONTH) + 1;
		result[2] = cal.get(Calendar.DATE);
		return result;
	}

	/**
	 * 得到指定日期的上一天的日期
	 * 
	 * @param date
	 *           格式：yyyyMMdd
	 * @return yyyyMMdd
	 */
	public static String getPreviousDate(String date)
	{
		int year = Integer.parseInt(date.substring(0, 4));
		int month = Integer.parseInt(date.substring(4, 6));
		int day = Integer.parseInt(date.substring(6, 8));

		int[] result = findYearMonthAndDay(year, month, day, -1);

		return result[0] + (result[1] < 10 ? ("0" + result[1]) : ("" + result[1]))
				+ (result[2] < 10 ? ("0" + result[2]) : ("" + result[2]));
	}

	/**
	 * 得到指定日期的后一天的日期
	 * 
	 * @param date
	 *           格式：yyyyMMdd
	 * @return yyyyMMdd
	 */
	public static String getBackDate(String date)
	{
		int year = Integer.parseInt(date.substring(0, 4));
		int month = Integer.parseInt(date.substring(4, 6));
		int day = Integer.parseInt(date.substring(6, 8));

		int[] result = findYearMonthAndDay(year, month, day, 1);

		return result[0] + (result[1] < 10 ? ("0" + result[1]) : ("" + result[1]))
				+ (result[2] < 10 ? ("0" + result[2]) : ("" + result[2]));
	}

	/**
	 * 得到指定日期的前七天的日期
	 * 
	 * @param date
	 *           格式：yyyyMMdd
	 * @return yyyyMMdd
	 */
	public static String getPreviousSevenDate(String date)
	{
		int year = Integer.parseInt(date.substring(0, 4));
		int month = Integer.parseInt(date.substring(4, 6));
		int day = Integer.parseInt(date.substring(6, 8));

		int[] result = findYearMonthAndDay(year, month, day, -6);

		return result[0] + (result[1] < 10 ? ("0" + result[1]) : ("" + result[1]))
				+ (result[2] < 10 ? ("0" + result[2]) : ("" + result[2]));
	}

	/**
	 * 2011年10月
	 * 
	 * @param date
	 *           格式：yyyyMMdd或YYYYMM
	 * @return 2011年10月
	 */
	public static String toChinaXiumaDate(String date)
	{
		int year = Integer.parseInt(date.substring(0, 4));
		int month = Integer.parseInt(date.substring(4, 6));


		return year + "年" + month + "月";
	}

	/**
	 * 得到指定日期的上一个月的日期
	 * 
	 * @param date
	 *           格式：yyyyMMdd或YYYYMM
	 * @return yyyyMM
	 */
	public static String getPreMonthDate(String date)
	{
		int year = Integer.parseInt(date.substring(0, 4));
		int month = Integer.parseInt(date.substring(4, 6));
		int day;
		int dateLength = 8;
		if (date.length() == dateLength) {
			day = Integer.parseInt(date.substring(6, 8));
		} else {
			day = Integer.parseInt("01");
		}

		int[] result = findYearMonth(year, month, day, -1);
		return result[0] + (result[1] < 10 ? ("0" + result[1]) : ("" + result[1]))
				+ (result[2] < 10 ? ("0" + result[2]) : ("" + result[2]));
	}

	/**
	 * 得到指定日期的上一个年的日期
	 * 
	 * @param date
	 *           格式：yyyyMMdd
	 * @return yyyyMM
	 */
	public static String getPreYearDate(String date)
	{
		int year = Integer.parseInt(date.substring(0, 4));
		int month = Integer.parseInt(date.substring(4, 6));
		int day = Integer.parseInt(date.substring(6, 8));

		int[] result = findYearDate(year, month, day, -1);
		return result[0] + (result[1] < 10 ? ("0" + result[1]) : ("" + result[1]))
				+ (result[2] < 10 ? ("0" + result[2]) : ("" + result[2]));
	}

	/**
	 * 取得指定日期的相隔月数对应的日期
	 * 
	 * @param year
	 * @param month
	 * @param day
	 * @param months
	 *           相隔月数
	 * @return
	 */
	public static int[] findYearMonth(int year, int month, int day, int months)
	{
		int[] result = new int[3];
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, day);
		cal.add(Calendar.MONTH, months);

		result[0] = cal.get(Calendar.YEAR);
		result[1] = cal.get(Calendar.MONTH) + 1;
		result[2] = cal.get(Calendar.DATE);
		return result;
	}

	/**
	 * 取得指定日期的相隔年数对应的日期
	 * 
	 * @param year
	 * @param month
	 * @param day
	 * @param years
	 *           相隔年数
	 * @return
	 */
	public static int[] findYearDate(int year, int month, int day, int years)
	{
		int[] result = new int[3];
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, day);
		cal.add(Calendar.YEAR, years);

		result[0] = cal.get(Calendar.YEAR);
		result[1] = cal.get(Calendar.MONTH) + 1;
		result[2] = cal.get(Calendar.DATE);
		return result;
	}

	/**
	 * 校验传的日期是否是合法日期
	 * 
	 * @param date
	 *           格式:yyyyMMdd
	 * @return
	 */
	public static boolean isValidXiumaDate(String date)
	{
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
		;
		try
		{
			dateFormat.parse(date);
			return true;
		}
		catch (Exception e)
		{
			//如果throw java.text.ParseException或者NullPointerException，就说明格式不对 
			return false;
		}
	}

	/**
	 * 日期间相隔的天数
	 * 
	 * @param t1
	 * @param t2
	 * @return
	 * @throws ParseException
	 */
	public static int getBetweenDays(String t1, String t2) throws ParseException
	{
		DateFormat format = new SimpleDateFormat("yyyyMMdd");
		int betweenDays = 0;
		Date d1 = format.parse(t1);
		Date d2 = format.parse(t2);
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(d1);
		c2.setTime(d2);
		// 保证第二个时间一定大于第一个时间 
		if (c1.after(c2))
		{
			c1 = c2;
			c2.setTime(d1);
		}
		int betweenYears = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
		betweenDays = c2.get(Calendar.DAY_OF_YEAR) - c1.get(Calendar.DAY_OF_YEAR);
		for (int i = 0; i < betweenYears; i++)
		{
			c1.set(Calendar.YEAR, (c1.get(Calendar.YEAR) + 1));
			betweenDays += c1.getMaximum(Calendar.DAY_OF_YEAR);
		}
		return betweenDays + 1;
	}


	/**
	 * 日期字符串转换，页面显示格式为：yyyy-MM-dd HH:mm:dd
	 * 
	 * @param 参数为：Date类型
	 */
	public static String date2Stirng2Second(Date date)
	{
		return toString(date, DEFAULT_DATETIME_FORMAT);
	}

	/**
	 * 日期字符串转换，页面显示格式为：yyyy-MM-dd
	 * 
	 * @param 参数为：Date类型
	 */
	public static String date2Stirng(Date date)
	{
		return toString(date, DEFAULT_DATE_FORMAT);
	}

	/**
	 * 日期字符串转换，页面显示格式为：yyyy-MM-dd HH:mm:dd 参数为：String类型
	 * 
	 * @throws ParseException
	 */
	public static String date2Stirng2Second(String date) throws ParseException
	{
		return toString(date, DEFAULT_DATETIME_FORMAT);
	}

	/**
	 * 格式化时间 格式为：yyyy-MM-dd HH:mm:dd
	 * 
	 * @param dateStr
	 *           日期字符串
	 * @return Date类型
	 * @throws ParseException
	 */
	public static Date formatDateStirng(String dateStr) throws ParseException
	{
		return toDate(dateStr, DEFAULT_DATETIME_FORMAT);
	}

	/**
	 * @Title: formatDate
	 * @Description: TODO
	 * @param date
	 * @param pattern
	 * @return String
	 */
	public static String formatDate(Date date, String pattern)
	{
		DateFormat dateFormat = new SimpleDateFormat(pattern);
		return dateFormat.format(date);
	}

	public static Date getCurrentDate() {
		Calendar c = Calendar.getInstance();
		return c.getTime();
	}

	public static int getYear() {
		Calendar c = Calendar.getInstance();
		return c.get(Calendar.YEAR);
	}

	public static String getCurrentDateString(String pattern){
		SimpleDateFormat df = new SimpleDateFormat(pattern);
		Calendar calendar = Calendar.getInstance();
		Date newDate=calendar.getTime();
		return df.format(newDate);
	}

	/**
	 * 取传参所在月的第一天（即月初）
	 * @author JiaBin.Yu
	 * @date 2016-3-15  上午11:44:53
	 * @param dateStr
	 * @return
	 */
	public static String getFirstDayOfMonth(String dateStr) {
		String calString = "";
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
			Date date = sdf.parse(dateStr);
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			calendar.set(Calendar.DAY_OF_MONTH, 1);
			calString = (new SimpleDateFormat("yyyy-MM-dd")).format(calendar.getTime());
			System.out.println(calString);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return calString;
	}

	/**
	 * 取传参所在月的最后一天（即月末）
	 * @author JiaBin.Yu
	 * @date 2016-3-15  上午11:44:53
	 * @param dateStr
	 * @return
	 */
	public static String getFinalDayOfMonth(String dateStr) {
		String calString = "";
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
			Date date = sdf.parse(dateStr);
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
			calString = (new SimpleDateFormat("yyyy-MM-dd")).format(calendar.getTime());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return calString;
	}

    /**
     * @Title: toDate
     * @Description: 字符串转换成Date
     * @param dtf
     * @param zone
     * @param str
     * @return Date
     */
    public static Date toDate(DateTimeFormatter dtf, ZoneId zone, String str) {
        if(org.apache.commons.lang.StringUtils.isNotBlank(str)) {
            Instant instant = LocalDateTime.parse(str.trim(),dtf).atZone(zone).toInstant();
            return Date.from(instant);
        }

        return null;
    }

    /**
     * @Title: toDate
     * @Description: 字符串转换成日期格式Date
     * @param str
     * @return Date
     */
    public static Date toMidDate(String str) {
        if(org.apache.commons.lang.StringUtils.isNotBlank(str)) {
            Instant instant = LocalDate.parse(str.trim(),DEFAULT_DATE).atStartOfDay(ZONE).toInstant();
            return Date.from(instant);
        }

        return null;
    }

}


